<!--
 * @Description: 表单组件入口，在这里组装子表单
 * @Author: wyh19
 * @Date: 2021-05-21
-->
<template>
  <div ref="pageBlock" class="form-wrapper">
    <el-button type="primary" @click="handleSave">保存</el-button>
    <div data-section="基础信息" data-ismain></div>
    <div data-section="个人信息" data-for="form1"></div>
    <form1 ref="form1" form-key="form1" :data="formDataMap" :old-data="oldFormDataMap"
           :link-channel="linkChannel" @validate="handleValidate"
           @field-change="handleFieldChange" />
    <div data-section="高级信息" data-ismain></div>
    <div data-section="公司信息" data-for="form2"></div>
    <form2 ref="form2" form-key="form2" :data="formDataMap" :old-data="oldFormDataMap"
           :link-channel="linkChannel" @validate="handleValidate" />
    <div data-section="过往履历" data-ismain data-for="form3"></div>
    <form3 ref="form3" form-key="form3" :data="formDataMap" :old-data="oldFormDataMap"
           :link-channel="linkChannel" @validate="handleValidate" />
    <div class="anchor-wrapper">
      <anchor ref="anchor" :page-block="pageBlock" />
    </div>
  </div>
</template>

<script>
import Anchor from '@/components/anchor'
import Form1 from './form1'
import Form2 from './form2'
import Form3 from './form3'
import { ajaxGetData, ajaxGetOldData } from './demo'
export default {
  name: 'TheForm',
  components: {
    Anchor,
    Form1,
    Form2,
    Form3
  },
  props: {
    formType: {
      type: String,
      default: 'add'
    }
  },
  provide() {
    return {
      formType: this.formType
    }
  },
  data() {
    return {
      pageBlock: undefined,
      formDataMap: this.resolveDataToMap({
        name: '',
        age: undefined,
        education: undefined,
        gender: undefined,
        hobby: [],
        company: '',
        workList: [{}]
      }),
      oldFormDataMap: {},
      linkChannel: {}
    }
  },
  async created() {
    // 根据页面类型获取数据
    if (~['edit', 'detail', 'compare'].findIndex(i => i === this.formType)) {
      await this.getData()
    }
    if (~['compare'].findIndex(i => i === this.formType)) {
      await this.getOldData()
    }
  },
  mounted() {
    this.pageBlock = this.$refs['pageBlock']
  },
  methods: {
    handleFieldChange(key, value) {
      this.$set(this.linkChannel, key, value)
    },
    async getData() {
      const data = await ajaxGetData()
      this.formDataMap = this.resolveDataToMap(data)
    },
    async getOldData() {
      const data = await ajaxGetOldData()
      this.oldFormDataMap = this.resolveDataToMap(data)
    },
    resolveDataToMap(data) {
      const form1 = {
        name: data.name,
        age: data.age,
        education: data.education,
        gender: data.gender,
        hobby: data.hobby
      }
      const form2 = {
        company: data.company
      }
      const form3 = {
        workList: data.workList
      }
      return {
        form1,
        form2,
        form3
      }
    },
    reRenderAnchor() {
      if (this.$refs['anchor']) {
        this.$refs['anchor'].reRender()
      }
    },
    handleValidate(formKey, isValid) {
      // 通过formKey查找章节
      const section = this.pageBlock.querySelector(`[data-for=${formKey}]`)
      if (!isValid) {
        section?.setAttribute('data-tip', '')
      } else {
        section?.removeAttribute('data-tip')
      }
      this.$refs['anchor'].reRender()
    },
    handleSave() {
      // 解析出全部表单key值,通过key值获取组件ref
      const formKeys = Object.keys(this.formDataMap)
      const validResults = formKeys.map(formKey => this.$refs[formKey].validForm())
      // 如果所有校验通过
      if (validResults.every(r => r)) {
        // 校验通过，打印表单数据，这里不再单个输出子表单里的数据，
        // 而是组装成完正的表单数据
        const formData = {}
        formKeys.map(formKey => {
          // 增加去除警告的代码
          const section = this.pageBlock.querySelector(`[data-for=${formKey}]`)
          section?.removeAttribute('data-tip')
          const partFormData = this.$refs[formKey].formData
          Object.assign(formData, partFormData)
        })
        console.log(formData)
      } else {
        this.$message.warning('校验未通过')
        // 标记出相应的失败表单
        formKeys.map((formKey, index) => {
          const section = this.pageBlock.querySelector(`[data-for=${formKey}]`)
          if (!validResults[index]) {
            section?.setAttribute('data-tip', '')
          } else {
            section?.removeAttribute('data-tip')
          }
        })
      }
      this.$refs['anchor'].reRender()
    }
  }
}
</script>

<style scoped lang="scss">
.form-wrapper {
  position: relative;
  width: 100%;
  // 修改height为合适的演示高度
  height: 500px;
  // 增加背景色，主要是为了方便理解截图
  background: #efefef;
  padding: 16px;
  overflow-y: auto;
  // ! 注意文章8没有提到注释这里，
  // ! 同时各子表单项增加class=field-wrapper样式
  // ::v-deep input {
  //   width: 280px;
  // }
}
.anchor-wrapper {
  position: fixed;
  right: 0px;
  width: 220px;
  height: 300px;
  top: 30%;
  transform: translate(0, -50%);
}
div[data-section] {
  position: relative;
  font-size: 14px;
  font-weight: bold;
  color: #5c658d;
  padding: 14px 0;
  margin-left: 34px;
  &::before {
    content: attr(data-section);
  }
}
div[data-ismain] {
  font-size: 16px;
  font-weight: bold;
  margin-left: 28px;
  &::after {
    content: '';
    position: absolute;
    left: -16px;
    top: 14px;
    width: 4px;
    height: 16px;
    background: #5c658d;
    border-radius: 2px;
  }
}
</style>
